<?php
/**
 * Postgres
 *
 * @package php.db
 */

/**
 * Postgres 연결 클래스 
 *
 * @package php.db
 */
class Postgres extends DBClient {

	/** 
	 * 생성자
	 */
	public function __construct($option = '', $type = 'product') {
		parent::__construct($option, $type);
	}

	/**
	 * database 연결 생성
	 * 
	 * @return resource 연결 resource
	 */
	protected function _connect() {

		$str = sprintf("host=%s port=%s dbname=%s user=%s password=%s", 
				$this->host,
				$this->port,
				$this->db,
				$this->id,
				$this->pass
		);

		return pg_connect($str, constant($this->newlink));
	}

	/**
	 * 실행된 row 수 
	 *
	 * @return int 
	 */
	public function affectedRows() { 
		return pg_affected_rows($this->getResult());
	}

	/**
	 * 트랜잭션 시작 (구현중)
	 * 
	 * @return bool 
	 * @see Postgres::commit(), Postgres::rollback();
	 */
	public function begin () { 
		return $this->query("BEGIN WORK;");
	}

	/**
	 * 연결 닫기 
	 */
	public function close() {
		pg_close($this->getConnection());
	}


	/** 
	 * commit (구현중)
	 *
	 * @return bool
	 * @see Postgres::begin(), Postgres::rollback();
	 */
	public function commit() {
		return $this->query("COMMIT;");
	}

	/**
	 * 에러 메세지 리턴
	 * 
	 * @return string 에러 메세지 
	 */
	public function error() {
		return pg_last_error($this->getConnection());
	}

	/**
	 * 문자열 escape	
	 * 
	 * @param string $str  escape 될 문자열 
	 * @return string escape 된 문자열
	 */
	public function escape($str) { 
		return pg_escape_string($str);
	}

	/**
	 * 실행된 select 쿼리에 대해서 fetch 를 통해 한 행(row)을 리턴한다. 
	 *
	 * 리턴되는 값은 array('필드' => 'ㅁㅁㅁ', ...); 형태를 가진다. 
	 * 
	 * @param resource $result select 결과로 나온 resource
	 * @return array row 데이타 
	 */
	public function fetch($result) {
		return pg_fetch_assoc($result);
	}

	public function fetchAll($result) { 
		return pg_fetch_all($result);
	}

	/** 
	 * 메모리 해제 
	 * 
	 * @return bool
	 */
	public function free($result) { 
		return pg_free_result ($result);
	}

	/** 
	 * 일반 쿼리 실행 
	 * 
	 * <code>
	 * $db = DB_('postgres', 'test', true);
	 * 
	 * // 1. 기본 쿼리 실행 
	 * $db->query("insert into test_table values ('123', '456')");
	 *
	 * // 2. 바인딩 쿼리 실행 
	 * $db->query('insert into test_table values ($1, $2)', array('123','456'));
	 * 
	 * $db->close();
	 * </code>
	 * 
	 * @param string $sql 실행될 query , 바인딩 될 곳은 $1, $2 와 같은 형태로 표시 
	 * @param array	 $param 바인딩될 변수 
	 * @return resource 실행 resource
	 */
	public function query($query, $param = array()) {
		if (sizeof($param) > 0) { 
			$this->setResult(pg_query_params($this->getConnection(), $query, $param));
		} else { 
			$this->setResult(pg_query($this->getConnection(), $query));
		}

		return $this->getResult();
	}

	/**
	 * DBData  구함
	 *
	 * <code>
	 * 
	 * $db->getData('select * from test_table');
	 *
	 * $db->getData(array('select * from test_table where id = $1', array('aaa')));
	 * 
	 * $db->getData(array('sql' => 'select * from test_table where id = $1', 'param' => array('aaa')));
	 * 
	 * </code>
	 * 
	 * @param	string|array $query DB query
	 * @param	boolean $isOne 인덱스 한칸 옮기기
	 * @return	DBData 
	 */
	public function getData($query, $isOne = false) 
	{
		if (gettype($query) == "array") { 
			$this->query($query['sql'] || $query[0], $query['param'] || $query[1]);
		} else { 
			$this->query($query);	
		}

		$data = $this->createData($this->getResult());

		if (!$this->getResult())  
			$this->free($this->getResult());

		if ($isOne) 
			$data->next();

		return $data;
	}

	/**
	 * 쿼리의 결과로 나온 필드의 개수를 리턴한다.
	 *
	 * @param resource $result select 결과로 나온 resource
	 * @return int 필드개수 
	 */
	public function getFieldCount($result) {
		return pg_num_fields ($result);
	}

	/**
	 * 정해진 위치의 필드 이름을 얻어온다. 
	 *
	 * @param resource $result select 결과로 나온 resource
	 * @param int $i 필드 위치, 처음은 0 
	 * @return string 필드이름 
	 */
	public function getFieldName($result, $i) {
		return pg_field_name($result, $i);
	}

	/**
	 * 정해진 위치의 필드 타입을 얻어온다. 
	 *
	 * @param resource $result select 결과로 나온 resource
	 * @param int $i 필드 위치, 처음은 0 
	 * @return string 필드타입
	 */
	public function getFieldType($result, $i) {
		return pg_field_type($result, $i);
	}


	/**
	 * select 쿼리에 대해서 페이징된 DBData를 리턴한다. 
	 *
	 * <code>
	 * 
	 * $db->getPageData('select * from test_table', 1, 10);
	 *
	 * $db->getPageData(array('select * from test_table where id = $1', array('aaa')), 1, 10);
	 * 
	 * $db->getPageData(array('sql' => 'select * from test_table where id = $1', 'param' => array('aaa')), 1, 10);
	 * 
	 * </code>
	 *
	 * @param string|array $query select 쿼리
	 * @param int $page 현재 페이지  
	 * @param int $count 페이지당 리스트 개수 
	 * @return DBData
	 */
	public function getPageData($query, $page, $count = 10) {

		// 시작지점 계산하기 
		$start = ($page-1)*$count+1;

		if (gettype($query) == "array") { 
			if ($query['sql'])	$query['sql']	.= " limit $count offset $start";
			if ($query[0])		$query[0]		.= " limit $count offset $start";
		} else { 
			$query .= " limit $count offset $start";
		}

		return $this->getData($query, false);
	}

	/** 
	 * rollback (구현중)
	 *
	 * @return bool 
	 */
	public function rollback() {
		return $this->query("ROLLBACK;");
	}

	/**
	 * 커서 이동 
	 * 
	 * @param int $count 이동시킬 상대위치, 사직행은 0 
	 * @return bool
	 */
	public function seek($count) { 
		return pg_result_seek($this->getResult(), $count);
	}

	/**
	 * 쿼리 파싱하기 (prepare)
	 * 
	 * <code>
	 *  $db->prepare("test_query", 'select * from test_table where id = $1');
	 * </code>
	 * 
	 * @param string $name prepare될 구문 이름 
	 * @param string $query prepare될 구문, 구문중에 바인될 변수는 $1,$2 와 같은 형태로 표시된다. 
	 * @see Postgres::execute()
	 */
	public function prepare($name, $query) {
		$this->setResult(pg_prepare($this->getConnection(), $name, $query));
		return $this->getResult();
	}


	/**
	 * prepare 된 쿼리 실행 
	 *
	 * <code>
	 * $db = DB_('postgres','test', true);
	 *
	 * $db->prepare('test_query', 'select * from test_table where id = $1');
	 * echo $db->execute('test_query', array('test value'));
	 *
	 * $db->close();
	 * </code>
	 *
	 * @param string $name prepare된 쿼리 이름 
	 * @param array $data  바인딩될 값 리스트 
	 * @return resource 실행된 결과 리소스 
	 */
	public function execute($name, $data = array()) {
		$this->setResult(pg_execute($this->getConnection(), $name, $data));
		return $this->getResult();
	}

}

?>